﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace 数字华容道
{
    /// <summary>
    /// 棋盘.xaml 的交互逻辑
    /// </summary>
    public partial class 棋盘 : UserControl
    {
        Random rnd;
        public 棋盘()
        {
            InitializeComponent();
            rnd = new Random(Convert.ToInt32(DateTime.Now.ToString("HHmmssfff")));
        }

        Point 当前空位 = new Point();

        int _Num = 3;

        public int Num
        {
            get => _Num;
            set
            {
                _Num = value;
                if (value < 3)
                {
                    _Num = 3;
                }
                if (value > 8)
                {
                    _Num = 8;
                }
            }
        }

        public void 重置棋盘()
        {
            棋盘格.Children.Clear();
            初始化棋盘(_Num, _Num);
            打乱棋盘();
        }

        void 初始化棋盘(int 棋盘列数, int 棋盘行数)
        {
            bg.SetValue(Grid.RowSpanProperty, 棋盘行数);
            bg.SetValue(Grid.ColumnSpanProperty, 棋盘列数);
            棋盘格.RowDefinitions.Clear();
            棋盘格.ColumnDefinitions.Clear();
            var width = Width;
            var height = Height;
            for (int i = 0; i < 棋盘行数; i++)
            {
                double 棋子宽度 = (width == double.NaN ? 600 : (int)width) / 棋盘列数;
                棋盘格.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(棋子宽度) });
                棋盘格.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(棋子宽度) });
                for (int j = 0; j < 棋盘列数; j++)
                {
                    if (i == 棋盘列数 - 1 && j == 棋盘行数 - 1)
                    {
                        break;
                    }
                    var piece = new 棋子
                    {
                        编号 = i * 棋盘列数 + j + 1,
                        FontSizeEx = (int)棋子宽度 / 2,
                        当前位置 = new Point(j, i)
                    };
                    piece.MouseLeftButtonUp += Piece_MouseLeftButtonUp;
                    piece.SetValue(Grid.RowProperty, i);
                    piece.SetValue(Grid.ColumnProperty, j);
                    棋盘格.Children.Add(piece);
                }
            }
            for (int i = 0; i < 棋盘列数 * 棋盘行数; i++)
            {
                var piece = new 棋子
                {
                    编号 = i + 1
                };
            }
            当前空位 = new Point(棋盘列数 - 1, 棋盘行数 - 1);
        }

        void 打乱棋盘()
        {
            int 打乱最小步数 = 100;
            int 打乱最大步数 = 300;

            int 打乱步数 = rnd.Next(打乱最小步数, 打乱最大步数);

            Task.Run(() =>
            {
                for (int i = 0; i < 打乱步数; i++)
                {
                    //this.Dispatcher.Invoke(() => { 打乱棋盘一次(); });
                    打乱棋盘一次();
                    //Thread.Sleep(500);
                }
            });
        }

        void 打乱棋盘一次()
        {
            List<int> 所有方向 = new List<int> { 0/*上*/, 1/*右*/, 2/*下*/, 3/*左*/ };
            if (当前空位.X == 0)
            {
                所有方向.Remove(3);
            }
            else if (当前空位.X == _Num - 1)
            {
                所有方向.Remove(1);
            }
            if (当前空位.Y == 0)
            {
                所有方向.Remove(0);
            }
            else if (当前空位.Y == _Num - 1)
            {
                所有方向.Remove(2);
            }

            var 方向 = 所有方向[rnd.Next(所有方向.Count)];

            int 可移动棋子个数 = 0;

            int 被点击棋子横坐标 = 0;
            int 被点击棋子纵坐标 = 0;

            switch (方向)
            {
                //点击空位上方
                case 0:
                    可移动棋子个数 = (int)当前空位.Y;
                    被点击棋子横坐标 = (int)当前空位.X;
                    被点击棋子纵坐标 = rnd.Next(可移动棋子个数);
                    break;
                //点击空位右侧
                case 1:
                    可移动棋子个数 = _Num - (int)当前空位.X;
                    被点击棋子横坐标 = (int)当前空位.X + rnd.Next(可移动棋子个数);
                    被点击棋子纵坐标 = (int)当前空位.Y;
                    break;
                //点击空位下方
                case 2:
                    可移动棋子个数 = _Num - (int)当前空位.Y;
                    被点击棋子横坐标 = (int)当前空位.X;
                    被点击棋子纵坐标 = (int)当前空位.Y + rnd.Next(可移动棋子个数);
                    break;
                //点击空位左侧
                case 3:
                    可移动棋子个数 = (int)当前空位.X;
                    被点击棋子横坐标 = rnd.Next(可移动棋子个数);
                    被点击棋子纵坐标 = (int)当前空位.Y;
                    break;
                default:
                    break;
            }

            this.Dispatcher.Invoke(() =>
            {
                棋子? 被点击的棋子 = 棋盘格.Children.Cast<UIElement>()
                .OfType<棋子>()
                .FirstOrDefault(t => (int)t.当前位置.X == 被点击棋子横坐标 && (int)t.当前位置.Y == 被点击棋子纵坐标);

                if (被点击的棋子 is not null)
                {
                    点击棋子移动位置(被点击的棋子);
                }
            });
        }

        // 替换 Piece_MouseLeftButtonUp 方法为更简单的实现
        private void Piece_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (sender is 棋子 piece)
            {
                点击棋子移动位置(piece);
                if (判断是否成功())
                {
                    MessageBox.Show("成功了");
                }
            }
        }

        bool 判断是否成功()
        {
            var 所有棋子 = 棋盘格.Children.Cast<UIElement>()
                        .OfType<棋子>().Reverse();
            foreach (var 棋子 in 所有棋子)
            {
                if (棋子.编号 != 棋子.当前位置.Y * Num + 棋子.当前位置.X + 1)
                {
                    return false;
                }
            }

            return true;
        }

        void 点击棋子移动位置(棋子 piece)
        {
            // 获取被点击棋子的坐标
            int pieceX = (int)piece.当前位置.X;
            int pieceY = (int)piece.当前位置.Y;
            // 获取当前空位的坐标
            int emptyX = (int)当前空位.X;
            int emptyY = (int)当前空位.Y;

            // 如果在同一列且不在同一行，可以移动
            if (pieceX == emptyX && pieceY != emptyY)
            {
                // 判断移动方向（向下为1，向上为-1）
                int dir = pieceY < emptyY ? 1 : -1;
                // 从空位到被点击棋子之间的所有棋子依次移动
                for (int y = emptyY - dir; y != pieceY - dir; y -= dir)
                {
                    // 查找当前列、指定行的棋子
                    var movingPiece = 棋盘格.Children.Cast<UIElement>()
                        .OfType<棋子>()
                        .FirstOrDefault(t => (int)t.当前位置.X == pieceX && (int)t.当前位置.Y == y);
                    if (movingPiece != null)
                    {
                        // 更新棋子的行属性和当前位置
                        movingPiece.SetValue(Grid.RowProperty, y + dir);
                        movingPiece.当前位置 = new Point(pieceX, y + dir);
                    }
                }
                // 更新空位坐标
                当前空位 = new Point(emptyX, pieceY);
            }
            // 如果在同一行且不在同一列，可以移动
            else if (pieceY == emptyY && pieceX != emptyX)
            {
                // 判断移动方向（向右为1，向左为-1）
                int dir = pieceX < emptyX ? 1 : -1;
                // 从空位到被点击棋子之间的所有棋子依次移动
                for (int x = emptyX - dir; x != pieceX - dir; x -= dir)
                {
                    // 查找当前行、指定列的棋子
                    var movingPiece = 棋盘格.Children.Cast<UIElement>()
                        .OfType<棋子>()
                        .FirstOrDefault(t => (int)t.当前位置.X == x && (int)t.当前位置.Y == pieceY);
                    if (movingPiece != null)
                    {
                        // 更新棋子的列属性和当前位置
                        movingPiece.SetValue(Grid.ColumnProperty, x + dir);
                        movingPiece.当前位置 = new Point(x + dir, pieceY);
                    }
                }
                // 更新空位坐标
                当前空位 = new Point(pieceX, emptyY);
            }
        }
    }
}
